package com.xiaoshuidi.cloud.module.iot.service.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.fastjson.JSONObject;
import com.xiaoshuidi.cloud.module.iot.dal.model.callback.YinTongWuLianCallReqVO;
import com.xiaoshuidi.cloud.module.iot.dal.model.device.TbDeviceDosageCallbackModel;
import com.xiaoshuidi.cloud.module.iot.dal.pojo.TbDeviceDo;
import com.xiaoshuidi.cloud.module.iot.dal.pojo.TbDeviceDosageDo;
import com.xiaoshuidi.cloud.module.iot.dal.pojo.TbDoorlockPassword;
import com.xiaoshuidi.cloud.module.iot.dal.repository.DeviceRepository;
import com.xiaoshuidi.cloud.module.iot.dal.repository.TbDoorLockPasswordRepository;
import com.xiaoshuidi.cloud.module.iot.enums.BrandEnum;
import com.xiaoshuidi.cloud.module.iot.enums.PassWordStatusEnum;
import com.xiaoshuidi.cloud.module.iot.enums.YinTongDataTypeEnum;
import com.xiaoshuidi.cloud.module.iot.enums.YinTongDevTypeEnum;
import com.xiaoshuidi.cloud.module.iot.service.CacheService;
import com.xiaoshuidi.cloud.module.iot.service.LocalCallbackService;
import com.xiaoshuidi.cloud.module.iot.service.YinTongWuLiaCallbackService;
import com.xiaoshuidi.cloud.module.iot.uitils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;

@Service
@Slf4j
public class YinTongWuLianCallbackServiceImpl implements YinTongWuLiaCallbackService {

    private static final String REDIS_DEVICE_PREFIX = "yintong:device:";

    private static final String YIN_TONG_SUCCESS_CODE = "1";

    private static final int PWD_RECORD_STATUS_UN_EFFECTIVE = 0;


    /**
     * 抄表时当前读数小于上一次读数
     */
    private static final String ALARM_CODE_1 = "1";

    @Autowired
    private LocalCallbackService localCallbackService;

    @Autowired
    private TbDoorLockPasswordRepository doorLockPasswordDataAccess;

    @Autowired
    private DeviceRepository deviceDataAccess;

    @Autowired
    private CacheService cacheService;

    @Override
    public void dealData(YinTongWuLianCallReqVO vo) {
        String dataType = vo.getDataType();
        YinTongDataTypeEnum instanceByDataTypeCode = YinTongDataTypeEnum.getInstanceByDataTypeCode(dataType);
        log.info("银通物联推送消息类型__操作id{}：操作类型{}", vo.getOperationId(), instanceByDataTypeCode.getDataTypeDesc());
        switch (instanceByDataTypeCode) {
            case METER_READ:
                dealMeterRead(vo);
                break;
            case OPEN_CLOSE:
                dealOpenClose(vo);
                break;
            case EXECUTE_RESULT:
                dealExecuteResult(vo);
                break;
            case LOCK_BATTERY:
                dealLockBattery(vo);
                break;
            case DEV_ONLINE:
                dealDevOnline(vo);
                break;
            case LOCK_OPEN:
                dealLockOpen(vo);
                break;
            case LOCK_PWD_RESULT:
                dealLockPwdResult(vo);
                break;
            default:
                log.error("银通物联推送消息为水滴无需处理的消息类型 {}", dataType);
                return;
        }
    }

    private void dealLockPwdResult(YinTongWuLianCallReqVO vo) {
        doDealLockEvent(vo);
    }


    private void dealMeterRead(YinTongWuLianCallReqVO vo) {
        String devSn = vo.getDevSn();
        // 阀门状态 0-开 1-关 断电 通电
        String valveStatus = vo.getValveStatus();
        // 当前读数
        String readValue = vo.getReadValue();
        // 在线状态 0-离线 1-在线
        String onlineStatus = vo.getOnlineStatus();
        // 告警状态，0-正常  1-本次读数小于上一次读数
        String alarmCode = vo.getAlarmCode();
        if (ALARM_CODE_1.equals(alarmCode) || StringUtils.isEmpty(readValue)) {
            log.error("解析银通物联抄表数据时发现当前读数小于上一次读数 {}，{}", alarmCode, readValue);
            return;
        }
        String collectTime = vo.getCollectTime();
        LocalDateTime reportDate = LocalDateTimeUtil.parse(collectTime, "yyyy-MM-dd HH:mm:ss");
        if (null == reportDate) {
            log.error("解析银通物联抄表推送数据时，发生异常 {}", collectTime);
            return;
        }
        TbDeviceDosageCallbackModel tbDeviceDosageCallbackModel = new TbDeviceDosageCallbackModel();
        // 该参数可以用来构建 查询tb_device 中设备信息的参数
        TbDeviceDo paramTbDeviceDo = buildTbDeviceDoParam(devSn);
        tbDeviceDosageCallbackModel.setTbDeviceDo(paramTbDeviceDo);
        TbDeviceDosageDo tbDeviceDosageDo = buildDeviceDosageParam(readValue, reportDate);
        tbDeviceDosageCallbackModel.setTbDeviceDosageDo(tbDeviceDosageDo);
        tbDeviceDosageCallbackModel.setOnlineStatus(parseOnlineStatus(onlineStatus));
        tbDeviceDosageCallbackModel.setPowerStatus(parseReadPowerStatusToSassStatus(valveStatus));
        tbDeviceDosageCallbackModel.setRoomCode(vo.getRoomCode());
        localCallbackService.disposeDeviceDosage(tbDeviceDosageCallbackModel);
    }

    private TbDeviceDosageDo buildDeviceDosageParam(String readValue, LocalDateTime reportDate) {
        TbDeviceDosageDo tbDeviceDosageDo = new TbDeviceDosageDo();
        tbDeviceDosageDo.setCreateTime(reportDate);
        tbDeviceDosageDo.setEndAmount((double) Integer.parseInt(readValue) / 1000);
        return tbDeviceDosageDo;
    }


    private TbDeviceDo buildTbDeviceDoParam(String devSn) {
        TbDeviceDo paramTbDeviceDo = new TbDeviceDo();
        paramTbDeviceDo.setDeviceThirdNo(devSn);
        paramTbDeviceDo.setBrandNo(BrandEnum.YINTONGWULIAN.getBrand());
        paramTbDeviceDo.setBrandName(BrandEnum.YINTONGWULIAN.getBrandName());
        return paramTbDeviceDo;
    }

    /**
     * 该类型的消息仅是水电表的通断电操作；主动发起通断电操作响应成功后，银通会再推送1次操作的结果回调，这里的回调记录仅进行状态通知，而不关注调用的是否成功或者失败
     * 出于变动场景的考虑，在主动发起时，会进行一下redis记录 yintong:ammeter:uuid:1        1通电  0断电 其中 1，代表的通电指令，0 代表断电指令，有效时间为3天
     * note:关于删除通断电请求的redis缓存的逻辑放入另一个事件处理中,因为不确定事件到来的先后顺序以及该事件是否一定到来 {@link #doDealAmmeterOrWaterMeterEvent(YinTongWuLianCallReqVO)}
     *
     * @param vo 银通推送的消息
     */
    private void dealOpenClose(YinTongWuLianCallReqVO vo) {
        String devSn = vo.getDevSn();
        String powerStatus = vo.getValveStatus();
        TbDeviceDo tbDeviceDo = new TbDeviceDo();
        tbDeviceDo.setDeviceThirdNo(devSn);
        tbDeviceDo.setBrandNo(BrandEnum.YINTONGWULIAN.getBrand());
        tbDeviceDo.setPowerStatus(Integer.valueOf(powerStatus));
        try {
            boolean count = localCallbackService.updateTbDeviceRecord(tbDeviceDo);
            log.error("更新设备 {} 通断电状态", devSn);
            if (!count) {
                log.error("更新设备 {}", devSn);
            }
        } catch (Exception e) {
            log.error("更新设备 {} 通断电状态发生错误", devSn, e);
        }
    }

    /**
     * 处理银通物联的回调接口，包括 增加，删除密码，修改密码以及 通电，断电,通水,断水接口
     * 通电断电逻辑：请求成功，都认为通断电成功，根据消息的结果来决定是否回滚
     * 修改密码接口：redis中存储的密码，对应的是旧密码，旧密码的生效时间段；处理逻辑是回调失败，则更改对应密码记录的 密码内容，生效时间断，修改时间，状态到执行成功；成功则更改原纪录到生效
     * 删除密码接口：请求成功时，会将密码状态修改为执行中 ；如果消息推送结果为成功，则更改记录状态到0；否则回滚密码状态到 1
     *
     * @param vo 推送数据
     */
    private void dealExecuteResult(YinTongWuLianCallReqVO vo) {
        // 1冷水表，2电表，3门锁，4热水表
        String devType = vo.getDevType();
        if (devType.equals(YinTongDevTypeEnum.LOCK.getCode())) {
            return;
        }
        if (YinTongDevTypeEnum.AMMETER.getCode().equals(devType) || YinTongDevTypeEnum.COLD.getCode().equals(devType) || YinTongDevTypeEnum.HOT.getCode().equals(devType)) {
            doDealAmmeterOrWaterMeterEvent(vo);
            return;
        }
        log.error("银通物联新的设备类型 {} 不在处理范围内", devType);
    }

    /**
     * 通电断电逻辑：请求成功，都认为通断电成功，根据消息的结果来决定是否回滚
     * 出于变动场景的考虑，在主动发起时，会进行一下redis记录 yintong:ammeter:uuid:1        1通电  0断电 其中 1，代表的通电指令，0 代表断电指令，有效时间为3天
     * note:关于删除通断电请求的redis缓存放入该事件处理中{@link #dealOpenClose(YinTongWuLianCallReqVO)}
     *
     * @param vo 推送结果
     */
    private void doDealAmmeterOrWaterMeterEvent(YinTongWuLianCallReqVO vo) {
        String operationId = vo.getOperationId();
        String isSuccess = vo.getIsSuccess();
        String devSn = vo.getDevSn();
        String onOrOffCode = "";
        try {
            onOrOffCode = cacheService.getString(REDIS_DEVICE_PREFIX + operationId);
        } catch (Exception e) {
            // 无法获取到redis记录，是无法直到该结果是通电结果或者断电结果，故无法做处理
            log.error("更新设备 {} 通断电状态前获取redis缓存时发生错误,正确的状态仅能靠刷新维护", operationId, e);
            return;
        }
        if (StringUtils.isEmpty(onOrOffCode)) {
            log.error("更新设备 {} 通断电状态前获取redis缓存时发生错误,正确的状态仅能靠刷新维护", operationId);
            return;
        }
        // 判断最终状态 通电1成功1则状态为通电1,通电1失败0则状态为断电0,断电0成功1则状态为断电0,断电0失败0则状态为通电1;异或逻辑是两个输入相同则为0,不同则为1;
        // 这里的状态是 银通状态
        int nextStatus = 1 ^ (parseOnlineStatus(isSuccess) ^ parseOnlineStatus(onOrOffCode));
        YinTongWuLianCallReqVO paramVo = new YinTongWuLianCallReqVO();
        if ("1".equals(isSuccess)) {
            if (vo.getValveStatus().equals("0")) {
                paramVo.setValveStatus("1");
            } else {
                paramVo.setValveStatus("0");
            }
        } else {
            paramVo.setValveStatus("0");
        }
        paramVo.setDevSn(devSn);
        dealOpenClose(paramVo);
    }

    /**
     * 密码的增删改都通过该回调消息进行确认
     * 新增密码，db在回调到来之前，状态为执行中，成功回调改为生效，失败改为下发失败
     * 修改密码，db中仅变更旧密码的状态为执行中，成功回调，修改记录的密码，生效时间及状态；否则将旧纪录的状态根据时间判断是超时还是有效
     * 删除密码，db中仅变更记录的状态执行中，成功回调，修改记录到status =0 ；失败回调，修改密码的失败回调相似处理
     *
     * @param vo 回调内容
     */
    private void doDealLockEvent(YinTongWuLianCallReqVO vo) {
        String operationId = vo.getOperationId();
        String isSuccess = vo.getIsSuccess();
        String pwdRedisText;
        try {
            pwdRedisText = cacheService.getString(REDIS_DEVICE_PREFIX + operationId);
            log.info("redis cache: {}", pwdRedisText);
        } catch (Exception e) {
            // 无法获取到redis记录，是无法直到该结果是通电结果或者断电结果，故无法做处理
            log.error("更新门锁设备 {} 密码前获取redis缓存时发生错误,部分密码业务将无法处理", operationId, e);
            return;
        }
        if (StringUtils.isEmpty(pwdRedisText)) {
            log.error("更新门锁设备 {} 密码前获取redis缓存时发生错误,部分密码业务将无法处理", operationId);
            return;
        }
        TbDoorlockPassword paramPwd = new TbDoorlockPassword();
        PWDRedisContent pwdRedisContent = JSONObject.parseObject(pwdRedisText, PWDRedisContent.class);
        String devSn = vo.getDevSn();
        TbDeviceDo tbDeviceDo = new TbDeviceDo();
        tbDeviceDo.setDeviceThirdNo(devSn);
        tbDeviceDo.setBrandNo(BrandEnum.YINTONGWULIAN.getBrand());
        TbDeviceDo tbDevice = deviceDataAccess.getTbDeviceByConditon(tbDeviceDo);
        if (null == tbDevice) {
            log.error("处理银通物联密码问题时检测到不存在的设备");
            return;
        }
        paramPwd.setDeviceNo(tbDevice.getDeviceNo());
        paramPwd.setThirdPasswordId(pwdRedisContent.getPasswordId());
        String actionType = pwdRedisContent.getActionType();
        log.info("redis门锁缓存的数据__操作id:{} 缓存操作类型：{} 操作结果：{} 缓存：{}", vo.getOperationId(), actionType, isSuccess, pwdRedisContent);
        boolean success = YIN_TONG_SUCCESS_CODE.equals(isSuccess);
        switch (actionType) {
            case "add":
                paramPwd.setPasswordStatus(Integer.parseInt(success ? PassWordStatusEnum.EFFECTIVE.getCode() : PassWordStatusEnum.FAIL.getCode()));
                log.info("新增密码持久化数据__操作id:{} 内容：{}", vo.getOperationId(), JSONObject.toJSONString(paramPwd));
                doorLockPasswordDataAccess.updateDoorLockPasswordRecordByDeviceNoAndPasswordId(paramPwd);
                break;
            case "edit":
                paramPwd.setPasswordStatus(Integer.parseInt(PassWordStatusEnum.EFFECTIVE.getCode()));
                if (!success) {
                    paramPwd.setPassword(pwdRedisContent.getOldPasswordContent());
                    paramPwd.setValidStarttime(DateUtils.parseDateInCST(pwdRedisContent.getOldPasswordStartTime()));
                    paramPwd.setValidEndtime(DateUtils.parseDateInCST(pwdRedisContent.getOldPasswordEndTime()));
                }
                log.info("修改密码持久化数据__操作id:{} 内容：{}", vo.getOperationId(), JSONObject.toJSONString(paramPwd));
                doorLockPasswordDataAccess.updateDoorLockPasswordRecordByDeviceNoAndPasswordId(paramPwd);
                break;
            case "del":
                if (success) {
                    log.info("删除密码(密码状态设置为过期)持久化数据__操作id:{} 内容：{}", vo.getOperationId(), JSONObject.toJSONString(paramPwd));
                    paramPwd.setStatus(PWD_RECORD_STATUS_UN_EFFECTIVE);
                    paramPwd.setDeleted(true);
//                    paramPwd.setPasswordStatus(Integer.parseInt(PassWordStatusEnum.EXPIRE.getCode()));
                } else {
                    paramPwd.setPasswordStatus(Integer.parseInt(PassWordStatusEnum.EFFECTIVE.getCode()));
                }
                log.info("删除密码持久化数据__操作id:{} 内容：{}", vo.getOperationId(), JSONObject.toJSONString(paramPwd));
                doorLockPasswordDataAccess.updateDoorLockPasswordRecordByDeviceNoAndPasswordId(paramPwd);
                break;
            case "frozen":
                if (success) {
                    paramPwd.setPasswordStatus(Integer.parseInt(PassWordStatusEnum.FROZEN.getCode()));
                } else {
                    paramPwd.setPasswordStatus(Integer.parseInt(PassWordStatusEnum.EFFECTIVE.getCode()));
                }
                log.info("冻结密码持久化数据__操作id:{} 内容：{}", vo.getOperationId(), JSONObject.toJSONString(paramPwd));
                doorLockPasswordDataAccess.updateDoorLockPasswordRecordByDeviceNoAndPasswordId(paramPwd);
                break;
            case "unFrozen":
                if (success) {
                    paramPwd.setPasswordStatus(Integer.parseInt(PassWordStatusEnum.EFFECTIVE.getCode()));
                } else {
                    paramPwd.setPasswordStatus(Integer.parseInt(PassWordStatusEnum.FROZEN.getCode()));
                }
                log.info("解冻密码持久化数据__操作id:{} 内容：{}", vo.getOperationId(), JSONObject.toJSONString(paramPwd));
                doorLockPasswordDataAccess.updateDoorLockPasswordRecordByDeviceNoAndPasswordId(paramPwd);
            default:
                log.error("redis 中记录未知的密码操作类型 {}", actionType);
                return;
        }
    }

    private void dealLockBattery(YinTongWuLianCallReqVO vo) {
        String devSn = vo.getDevSn();
        double batteryLevel = parseBatteryLevel(vo.getReadValue());
        String collectTime = vo.getCollectTime();
        TbDeviceDo tbDeviceDo = new TbDeviceDo();
        tbDeviceDo.setDeviceThirdNo(devSn);
        tbDeviceDo.setBrandNo(BrandEnum.YINTONGWULIAN.getBrand());
        tbDeviceDo.setReportTime(LocalDateTimeUtil.parse(collectTime, "yyyy-MM-dd HH:mm:ss"));
        tbDeviceDo.setBatteryLevel(batteryLevel);
        try {
            boolean count = localCallbackService.updateTbDeviceRecord(tbDeviceDo);
            log.error("更新门锁设备 {} 电量及报告时间成功", devSn);
            if (!count) {
                log.error("更新门锁设备 {} 电量及报告时间时受影响行数 {}", devSn, count);
            }
        } catch (Exception e) {
            log.error("更新门锁设备 {} 电量及报告时间时发生错误", devSn, e);
        }
    }

    private double parseBatteryLevel(String readValue) {
        double batteryLevel = 0;
        try {
            batteryLevel = Double.parseDouble(readValue);
        } catch (NumberFormatException e) {
            log.error("解析银通物联的门锁电量时解析失败,原数据 {}", readValue);
        }
        return batteryLevel;
    }

    private void dealDevOnline(YinTongWuLianCallReqVO vo) {
        String devSn = vo.getDevSn();
        int onlineStatus = parseOnlineStatus(vo.getOnlineStatus());
        String collectTime = vo.getCollectTime();
        TbDeviceDo tbDeviceDo = new TbDeviceDo();
        tbDeviceDo.setDeviceThirdNo(devSn);
        tbDeviceDo.setBrandNo(BrandEnum.YINTONGWULIAN.getBrand());
        tbDeviceDo.setReportTime(LocalDateTimeUtil.parse(collectTime, "yyyy-MM-dd HH:mm:ss"));
        tbDeviceDo.setOnlineStatus(onlineStatus);
        try {
            boolean count = localCallbackService.updateTbDeviceRecord(tbDeviceDo);
            log.error("更新设备 {} 在线状态及报告时间成功", devSn);
            if (!count) {
                log.error("更新设备 {} 在线状态及报告时间时受影响行数 {}", devSn, count);
            }
        } catch (Exception e) {
            log.error("更新设备 {}  在线状态及报告时间时发生错误", devSn, e);
        }
    }

    private void dealLockOpen(YinTongWuLianCallReqVO vo) {
        log.info("开门记录推送数据：" + JSONObject.toJSONString(vo));
        String devSn = vo.getDevSn();
        String thirdPasswordId = vo.getUserId();
        String collectTime = vo.getCollectTime();
        //先查询该设备是否存在
        TbDeviceDo tbDeviceDo = new TbDeviceDo();
        tbDeviceDo.setDeviceThirdNo(devSn);
        tbDeviceDo.setBrandNo(BrandEnum.YINTONGWULIAN.getBrand());
        JSONObject openRecord = new JSONObject();
        openRecord.put("userId", thirdPasswordId);
        openRecord.put("recordTime", DateUtils.parseDateInCST(collectTime));
        openRecord.put("opType", "offlinePwd");//离线密码开锁
        TbDeviceDosageCallbackModel tbDeviceDosageCallbackModel = new TbDeviceDosageCallbackModel();
        tbDeviceDosageCallbackModel.setOpenRecord(openRecord);
        tbDeviceDosageCallbackModel.setTbDeviceDo(tbDeviceDo);
        try {
            localCallbackService.disposeOpenRecordCallback(tbDeviceDosageCallbackModel);
        } catch (Exception e) {
            log.error("处理门锁{}的密码 {} 开门记录时发生错误", devSn, thirdPasswordId, e);
        }
    }

    private int parseOnlineStatus(String readValue) {
        int onlineStatus = 0;
        try {
            onlineStatus = Integer.parseInt(readValue);
        } catch (NumberFormatException e) {
            log.error("解析银通物联的在线状态时报错 ,原数据 {}", readValue);
        }
        return onlineStatus;
    }

    /**
     * 将抄表时的读取到的通断电状态转为 saas里的通断电状态
     * readValue中 1表示断电/断水 0表示通电/通水；与 saas 相反
     *
     * @param readValue 银通回调的状态
     * @return saas里的状态
     */
    private int parseReadPowerStatusToSassStatus(String readValue) {
        int onlineStatus = 1;
        try {
            onlineStatus = Integer.parseInt(readValue);
        } catch (NumberFormatException e) {
            log.error("解析银通物联的在线状态时报错 ,原数据 {}", readValue);
        }
        return onlineStatus & 1;
    }

    /**
     * json字符串如下
     * {"passwordId":"","passwordContent":"","pwdType":"","actionTime":"yyyy-MM-dd HH:mm:ss","passwordStartTime":"","passwordEndTime":"","actionType":"",
     * "oldPasswordStartTime":"","oldPasswordEndTime":"","oldPasswordContent":""}
     */
    static class PWDRedisContent {

        String passwordId;
        // 旧密码
        String passwordContent;
        // 0永久使用  1单次使用  2时限使用（管理员密码只能使用永久密码）
        String pwdType;
        // 执行时间
        String actionTime;
        // 生效起始时间
        String passwordStartTime;
        String passwordEndTime;
        // "edit"  "del" "add"
        String actionType;
        String oldPasswordStartTime;
        String oldPasswordEndTime;
        String oldPasswordContent;

        public String getPasswordId() {
            return passwordId;
        }

        public void setPasswordId(String passwordId) {
            this.passwordId = passwordId;
        }

        public String getPasswordContent() {
            return passwordContent;
        }

        public void setPasswordContent(String passwordContent) {
            this.passwordContent = passwordContent;
        }

        public String getPwdType() {
            return pwdType;
        }

        public void setPwdType(String pwdType) {
            this.pwdType = pwdType;
        }

        public String getActionTime() {
            return actionTime;
        }

        public void setActionTime(String actionTime) {
            this.actionTime = actionTime;
        }

        public String getPasswordStartTime() {
            return passwordStartTime;
        }

        public void setPasswordStartTime(String passwordStartTime) {
            this.passwordStartTime = passwordStartTime;
        }

        public String getPasswordEndTime() {
            return passwordEndTime;
        }

        public void setPasswordEndTime(String passwordEndTime) {
            this.passwordEndTime = passwordEndTime;
        }

        public String getActionType() {
            return actionType;
        }

        public void setActionType(String actionType) {
            this.actionType = actionType;
        }

        public String getOldPasswordStartTime() {
            return oldPasswordStartTime;
        }

        public void setOldPasswordStartTime(String oldPasswordStartTime) {
            this.oldPasswordStartTime = oldPasswordStartTime;
        }

        public String getOldPasswordEndTime() {
            return oldPasswordEndTime;
        }

        public void setOldPasswordEndTime(String oldPasswordEndTime) {
            this.oldPasswordEndTime = oldPasswordEndTime;
        }

        public String getOldPasswordContent() {
            return oldPasswordContent;
        }

        public void setOldPasswordContent(String oldPasswordContent) {
            this.oldPasswordContent = oldPasswordContent;
        }

        @Override
        public String toString() {
            return "PWDRedisContent{" +
                    "passwordId='" + passwordId + '\'' +
                    ", passwordContent='" + passwordContent + '\'' +
                    ", pwdType='" + pwdType + '\'' +
                    ", actionTime='" + actionTime + '\'' +
                    ", passwordStartTime='" + passwordStartTime + '\'' +
                    ", passwordEndTime='" + passwordEndTime + '\'' +
                    ", actionType='" + actionType + '\'' +
                    ", oldPasswordStartTime='" + oldPasswordStartTime + '\'' +
                    ", oldPasswordEndTime='" + oldPasswordEndTime + '\'' +
                    ", oldPasswordContent='" + oldPasswordContent + '\'' +
                    '}';
        }
    }
}
